﻿#if NETCORE

using Apewer.Network;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Apewer.Web
{

    /// <summary>用于网站的服务程序。</summary>
    public class AspNetCoreProvider : ApiProvider<HttpContext>
    {

        private HttpContext context;
        private HttpRequest request;
        private HttpResponse response;

        /// <summary>HttpContext</summary>
        public override HttpContext Context { get => context; }

        /// <summary>创建服务程序实例。</summary>
        /// <exception cref="ArgumentNullException"></exception>
        public AspNetCoreProvider(HttpContext context)
        {
            if (context == null) throw new ArgumentNullException(nameof(context));
            this.context = context;
            request = context.Request;
            response = context.Response;
        }

        #region Request

        /// <summary>获取 HTTP 方法。</summary>
        public override Network.HttpMethod GetMethod() => ApiUtility.Method(request.Method);

        /// <summary>获取客户端的 IP 地址。</summary>
        public override string GetClientIP() => request.HttpContext.Connection.RemoteIpAddress.ToString();

        /// <summary>获取请求的 URL。</summary>
        public override Uri GetUrl()
        {
            var https = request.IsHttps;
            var port = Context.Connection.LocalPort;
            var query = request.QueryString == null ? null : request.QueryString.Value;

            var sb = new StringBuilder();
            sb.Append(https ? "https://" : "http://");
            sb.Append(request.Host.Host ?? "");
            if ((https && port != 443) || (!https && port != 80))
            {
                sb.Append(":");
                sb.Append(port);
            }
            sb.Append(request.Path);
            if (!string.IsNullOrEmpty(query))
            {
                if (!query.StartsWith("?")) sb.Append("?");
                sb.Append(query);
            }

            var url = sb.ToString();
            var uri = new Uri(url);
            return uri;
        }

        /// <summary>获取请求的 Referrer。</summary>
        public override string GetReferrer() => null;

        /// <summary>获取请求的头。</summary>
        public override HttpHeaders GetHeaders()
        {
            var headers = request.Headers;
            var result = new HttpHeaders();
            if (headers == null) return result;
            foreach (var key in headers.Keys)
            {
                if (string.IsNullOrEmpty(key)) continue;
                try
                {
                    var value = headers[key];
                    if (string.IsNullOrEmpty(value)) continue;
                    result.Add(key, value);
                }
                catch { }
            }
            return result;
        }

        /// <summary>获取请求的内容类型。</summary>
        public override string GetContentType() => request.ContentType;

        /// <summary>获取请求的内容长度。</summary>
        public override long GetContentLength() => request.ContentLength ?? -1L;

        /// <summary>获取请求的内容。</summary>
        public override Stream RequestBody() => request.Body;

        #endregion

        #region Response

        /// <summary>设置 HTTP 状态。</summary>
        public override void SetStatus(int status, int subStatus = 0) => response.StatusCode = status;

        /// <summary>设置响应的头。</summary>
        public override string SetHeader(string name, string value)
        {
            try
            {
                response.Headers.Add(name, value);
            }
            catch (Exception ex)
            {
                Logger.Internals.Error(nameof(AspNetCoreProvider), nameof(SetHeader), ex.Message(), name, value);
                return ex.Message;
            }
            return null;
        }

        /// <summary>设置响应的缓存秒数，设置为 0 即不允许缓存。</summary>
        public override void SetCache(int seconds)
        {
            if (seconds > 0)
            {
                SetHeader("Cache-Control", $"public, max-age={seconds}, s-maxage={seconds}");
            }
            else
            {
                SetHeader("Cache-Control", "no-cache, no-store, must-revalidate");
                SetHeader("Pragma", "no-cache");
            }
        }

        /// <summary>设置响应的缓存秒数。</summary>
        public override void SetContentType(string value) => response.ContentType = value;

        /// <summary>设置响应的内容长度。</summary>
        public override void SetContentLength(long value) => response.ContentLength = value;

        /// <summary>设置响应重定向。</summary>
        public override void SetRedirect(string location) => SetRedirect(location, false);

        /// <summary>获取 Response 流。</summary>
        public override Stream ResponseBody() => response.Body;

        #endregion

        #region This

        /// <summary>将客户端重新定向到新 URL。</summary>
        /// <remarks>默认响应 302 状态。可指定 permanent = true 以响应 301 状态。</remarks>
        public void SetRedirect(string location, bool permanent = false)
        {
            try { response.Redirect(location, permanent); } catch { }
        }

        private static void Async(Stream source, Stream destination, Func<long, bool> progress = null, int buffer = 4096, Action after = null)
        {
            if (source == null || !source.CanRead || destination == null || !destination.CanWrite)
            {
                after?.Invoke();
                return;
            }

            Async(source, destination, progress, buffer, after, 0L);
        }

        private static void Async(Stream source, Stream destination, Func<long, bool> progress, int buffer, Action after, long total)
        {
            // 缓冲区。
            var limit = buffer < 1 ? 1 : buffer;
            var temp = new byte[limit];

            // 读取一次。
            try
            {
                source.BeginRead(temp, 0, limit, (ar1) =>
                {
                    var count = source.EndRead(ar1);
                    if (count > 0)
                    {
                        destination.BeginWrite(temp, 0, count, (ar2) =>
                        {
                            destination.EndWrite(ar2);
                            total += count;
                            if (progress != null)
                            {
                                var @continue = progress.Invoke(total);
                                if (!@continue)
                                {
                                    after?.Invoke();
                                    return;
                                }
                            }
                            Async(source, destination, progress, buffer, after, total);
                        }, null);
                    }
                    else after?.Invoke();
                }, null);
            }
            catch { }
        }

        /// <summary>解析 URL 的查询字符串，获取所有已解码的参数。</summary>
        public static StringPairs ParseQuery(HttpRequest request)
        {
            if (request == null) return new StringPairs();

            var sp = new StringPairs();
            if (request.Query == null) return sp;

            var keys = request.Query.Keys;
            sp.Capacity = keys.Count;
            foreach (var key in keys)
            {
                sp.Add(key, request.Query[key]);
            }
            sp.Capacity = sp.Count;
            return sp;
        }

        #endregion

    }

}

#endif
